home *** CD-ROM | disk | FTP | other *** search
/ MacTech 1 to 12 / MacTech-vol-1-12.toast / Source / MacTech® Magazine / Volume 10 - 1994 / 10.02 Feb 94 / DigiSign / SoundByte.c < prev    next >
Encoding:
Text File  |  1993-12-03  |  17.8 KB  |  810 lines  |  [TEXT/KAHL]

  1. // Contains main, add this and SoundByteUtils.c to a project
  2. // along with MacTraps lib in Think C or compiled with the
  3. // usual C libraries in MPW.  This has not been compiled
  4. // under MPW but you should have very little problems if any
  5. // doing so.
  6.  
  7. #include <EPPC.h>
  8. #include <Menus.h>
  9. #include <Sound.h>
  10. #include <SoundInput.h>
  11. #include <AppleEvents.h>
  12. #include <Script.h>
  13.  
  14. #include "OCEErrors.h"
  15. #include "DigitalSignature.h"
  16.  
  17. #include "SoundByte.h"
  18. #include "SoundByteUtils.h"
  19.  
  20. Environment gEnvironment;
  21.  
  22. void BeginProcessing(OperationType operation)
  23. {
  24.     Handle    item;
  25.     Rect    bounds;
  26.     Str255    message        = {0};
  27.     short    kind         = 0;
  28.     
  29.     SetCursor(*GetCursor(watchCursor));
  30.     
  31.     if (gEnvironment.statusDialog == nil)
  32.         {
  33.         gEnvironment.statusDialog = GetNewDialog(rStatusDialog, nil, kMoveToFront);
  34.         if (gEnvironment.statusDialog == nil)
  35.             AlertOSErr(MemError());
  36.         SetPort(gEnvironment.statusDialog);
  37.         }
  38.         
  39.     if (operation == kSigningOperation) 
  40.         kind = kSigning;
  41.     else if (operation == kVerifyingOperation)
  42.         kind = kVerifying;
  43.     else if (operation == kProcessingOperation)
  44.         kind = kProcessing;
  45.     else if (operation == kCancelingOperation)
  46.         kind = kCanceling;
  47.  
  48.     GetIndString(message, rOtherStrings, kind);
  49.     GetDItem(gEnvironment.statusDialog, iStatus, &kind, &item, &bounds);
  50.     SetIText(item, message);
  51.     
  52.     ShowWindow(gEnvironment.statusDialog);
  53.     SetPort(gEnvironment.statusDialog);
  54.     DrawDialog(gEnvironment.statusDialog);
  55. }
  56.  
  57. void EndProcessing()
  58. {
  59.     if (gEnvironment.statusDialog != nil)
  60.         {
  61.         DisposDialog(gEnvironment.statusDialog);
  62.         gEnvironment.statusDialog = nil;
  63.         SetPort(FrontWindow());
  64.         DrawDialog(FrontWindow());    // force an update here
  65.         }
  66.         
  67.     SetCursor(&qd.arrow);
  68. }
  69.  
  70. pascal Boolean SimpleStatusProc()
  71. {
  72.     GrafPtr        savePort;
  73.     EventRecord    event;
  74.     DialogPtr    aDialog;
  75.     short        item;
  76.     long         ignore;
  77.     Boolean        keepGoing = true;
  78.  
  79.     GetPort(&savePort);
  80.     SetPort(gEnvironment.statusDialog);
  81.     
  82.     if (WaitNextEvent(kProcessingEventMask, &event, kMinSleep, kNilMouseRgn)) 
  83.         {
  84.         if (FrontWindow() != gEnvironment.statusDialog)     // just in case
  85.             SelectWindow(gEnvironment.statusDialog);
  86.  
  87.         switch (event.what) 
  88.             {
  89.             case autoKey:
  90.             case keyDown:
  91.                 // poor mans way to cancel, see IM VI for localizable way!
  92.                 if (event.modifiers & cmdKey && (event.message & charCodeMask) == '.')
  93.                     keepGoing = false;
  94.                 break;
  95.             default:
  96.                 SetCursor(&qd.arrow);
  97.                 if (IsDialogEvent(&event) && DialogSelect(&event, &aDialog, &item) && aDialog == gEnvironment.statusDialog)
  98.                     keepGoing = false;
  99.                 SetCursor(*GetCursor(watchCursor));
  100.             }
  101.             
  102.         }
  103.  
  104.     if (keepGoing == false)
  105.         {
  106.         BeginProcessing(kCancelingOperation);
  107.         Delay(40, &ignore);    // delay so user can read the status dialog
  108.         }
  109.         
  110.     SetPort(savePort);
  111.         
  112.     return keepGoing;
  113. }
  114.  
  115. OSErr DoProcessData(SIGContextPtr context, SoundByteWindowPtr window)
  116. {
  117.     short    kind;
  118.     Handle    item;
  119.     Rect    bounds;
  120.     Str255    topic;
  121.     Size    soundLength;
  122.     Size    soundOffset    = 0;
  123.     Size    soundChunk    = kOurProcessDataSize;
  124.     OSErr    error         = noErr;
  125.     
  126.     do {
  127.         // digest the topic field
  128.         GetDItem((DialogPtr)window, iTopic, &kind, &item, &bounds);
  129.         GetIText(item, topic);
  130.         if (error = SIGProcessData(context, topic, topic[0]))
  131.             break;
  132.         if (SimpleStatusProc() == false)    // see if user want's to cancel
  133.             error = userCanceledErr;
  134.         
  135.         // if there is a sound, process it in kOurProcessDataSize chunks
  136.         if (window->sound == nil)
  137.             break;
  138.         soundLength = GetHandleSize(window->sound);
  139.         if (soundLength < soundChunk) 
  140.             soundChunk = soundLength;
  141.         HLock(window->sound);
  142.         do    {
  143.             if (error = SIGProcessData(context, (*window->sound)+soundOffset, soundChunk))
  144.                 break;
  145.             if (SimpleStatusProc() == false)            // see if user want's to cancel 
  146.                 {
  147.                 error = userCanceledErr;
  148.                 break;
  149.                 }
  150.             soundOffset+=soundChunk;                    // increment what we just processed
  151.             if ((soundOffset + soundChunk) > soundLength)    // preflight chunk for next pass 
  152.                 soundChunk = soundLength - soundOffset;
  153.             if (soundChunk <= 0)                        // when we process it all, bail
  154.                 break;
  155.             } while (true);
  156.         HUnlock(window->sound);
  157.         } while (0);
  158.         
  159.     return error;    
  160. }
  161.  
  162. OSErr AssociateSignersNameAndSoundByte(SIGContextPtr context, SoundByteWindowPtr window)
  163. {
  164.     SIGCertInfo             certInfo;
  165.     SIGNameAttributesInfo    attrInfo;
  166.     unsigned short            attrIndex;
  167.     OSErr                    error;
  168.     Str255                    attrValue        = {0};
  169.     
  170.     do {
  171.         // get the number of cert attributes
  172.         if (error = SIGGetCertInfo(context, kSIGSignerCertIndex, &certInfo))
  173.             break;
  174.         
  175.         // walk the attributes looking for the "right" one to store away
  176.         for (attrIndex = 0; attrIndex < certInfo.certAttributeCount; attrIndex++)
  177.             {
  178.             if (error = SIGGetCertNameAttributes(context, kSIGSignerCertIndex, attrIndex, &attrInfo))
  179.                 break;
  180.             if (attrInfo.attributeType == kSIGTitle)            // in case there is no name
  181.                 BlockMove(&attrInfo.attribute, &attrValue, sizeof(Str255));
  182.             else if (attrInfo.attributeType == kSIGCommonName)    // best thing to display
  183.                 {
  184.                 BlockMove(&attrInfo.attribute, &attrValue, sizeof(Str255));
  185.                 break;
  186.                 }
  187.             }
  188.         if (window->partOfName)
  189.             DisposHandle(window->partOfName);
  190.         error = PtrToHand(attrValue, &window->partOfName, attrValue[0] + 1);
  191.         } while (0);
  192.     
  193.     return error;
  194. }
  195.  
  196. void DoVerifying()
  197. {
  198.     OSErr                error;
  199.     SIGContextPtr         context    = nil;
  200.     SoundByteWindowPtr    window     = (SoundByteWindowPtr)FrontWindow();
  201.     
  202.     do {
  203.         window->state = kUnkownState;
  204.         BeginProcessing(kVerifyingOperation);
  205.         if (error = SIGNewContext(&context))
  206.             break;
  207.         HLock(window->signature);
  208.         error = SIGVerifyPrepare(context, (SIGSignaturePtr)*window->signature, GetHandleSize(window->signature), (SIGStatusProcPtr)SimpleStatusProc);
  209.         HUnlock(window->signature);
  210.         if (error)
  211.             break;
  212.         BeginProcessing(kProcessingOperation);
  213.         if (error = DoProcessData(context, window))
  214.             break;
  215.         BeginProcessing(kVerifyingOperation);
  216.         error = SIGVerify(context);
  217.         if (error && error != kSIGInvalidCredentialErr)
  218.             {
  219.             window->state = kInvalidState;
  220.             break;
  221.             }
  222.         if (error = AssociateSignersNameAndSoundByte(context, window))    // refresh name for safety
  223.             break;
  224.         window->state = kValidState;
  225.         EndProcessing();
  226.         error = SIGShowSigner(context, kNullPString);
  227.         } while (0);
  228.     
  229.     if (context) SIGDisposeContext(context);
  230.     EndProcessing();
  231.  
  232.     AlertOSErr(error);
  233. }
  234.  
  235. void DoSigning()
  236. {
  237.     OSErr                error;
  238.     Size                signatureSize;
  239.     SIGContextPtr         context        = nil;
  240.     SoundByteWindowPtr    window         = (SoundByteWindowPtr)FrontWindow();
  241.     
  242.     do {
  243.         if (error = SIGNewContext(&context))
  244.             break;
  245.         if (error = SIGSignPrepare(context, nil, kNullPString, &signatureSize))
  246.             break;
  247.         BeginProcessing(kProcessingOperation);
  248.         if (window->signature) 
  249.             SetHandleSize(window->signature, signatureSize);
  250.         else
  251.             window->signature = NewHandle(signatureSize);
  252.         if (error = MemError())
  253.             break;
  254.         HNoPurge(window->signature);
  255.         if (error = DoProcessData(context, window))
  256.             break;
  257.         BeginProcessing(kSigningOperation);
  258.         HLock(window->signature);
  259.         error = SIGSign(context, (SIGSignaturePtr)*window->signature, (SIGStatusProcPtr)SimpleStatusProc);
  260.         HUnlock(window->signature);
  261.         if (error)
  262.             break;
  263.         if (error = AssociateSignersNameAndSoundByte(context, window))
  264.             break;
  265.         window->state = kValidState;
  266.         } while (0);
  267.     
  268.     if (context) SIGDisposeContext(context);
  269.         
  270.     if (error && window->signature)
  271.         {
  272.         DisposHandle(window->signature);
  273.         window->signature = nil;
  274.         }
  275.     
  276.     EndProcessing();
  277.     AlertOSErr(error);
  278. }
  279.  
  280. pascal void AuthorDrawProc(DialogPtr dialog, short itemNumber)
  281. {
  282.     short                kind;
  283.     Handle                item;
  284.     Rect                bounds;
  285.     SoundByteWindowPtr    window    = (SoundByteWindowPtr)dialog;
  286.     
  287.     GetDItem(dialog, itemNumber, &kind, &item, &bounds);
  288.     
  289.     if (window->partOfName)
  290.         {
  291.         EraseRect(&bounds);
  292.         MoveTo(bounds.left + 20, bounds.bottom - 4);
  293.         DrawString((StringPtr)*window->partOfName);
  294.         
  295.         bounds.bottom -= 1;
  296.         bounds.right = bounds.left + 16;
  297.         bounds.top = bounds.bottom - 16;
  298.         
  299.         if (window->state == kValidState)
  300.             kind = kSIGValidSignatureIconResID;
  301.         else if (window->state == kInvalidState)
  302.             kind = kSIGInvalidSignatureIconResID;
  303.         else
  304.             kind = kSIGSignatureIconResID;
  305.         
  306.         PlotIconID(&bounds, 0, 0, kind);
  307.         }
  308.     else
  309.         {
  310.         PenPat(qd.gray);
  311.         FrameRect(&bounds);
  312.         PenNormal();
  313.         }
  314. }
  315.  
  316. OSErr SaveToDisk(SoundByteWindowPtr window, short currentResFile)
  317. {
  318.     OSErr    error;
  319.     short    kind;
  320.     Handle    item;
  321.     Rect    bounds;
  322.     Str255    topic;
  323.     Handle    topicHandle;
  324.  
  325.     do {
  326.         GetDItem((DialogPtr)window, iTopic, &kind, &item, &bounds);
  327.         GetIText(item, topic);
  328.         if (error = PtrToHand(topic, &topicHandle, topic[0] + 1))
  329.             break;
  330.         UseResFile(window->resRef);
  331.         RmveResource(Get1Resource(kTopicResType, kTopicResID));
  332.            RmveResource(Get1Resource(kSoundResType, kSoundResID));
  333.         RmveResource(Get1Resource(kNameResType, kNameResID));
  334.         AddResource(topicHandle, kTopicResType, kTopicResID, kNullPString);
  335.         if (error = ResError())
  336.             break;
  337.         if (window->signature)
  338.             AddResource(window->signature, kSignatureResType, kSignatureResID, kNullPString);
  339.         if (window->sound)
  340.             AddResource(window->sound, kSoundResType, kSoundResID, kNullPString);
  341.         if (window->partOfName)
  342.             AddResource(window->partOfName, kNameResType, kNameResID, kNullPString);
  343.         UpdateResFile(window->resRef);
  344.         if (window->signature)
  345.             DetachResource(window->signature);
  346.         if (window->sound)
  347.             DetachResource(window->sound);
  348.         if (window->partOfName)
  349.             DetachResource(window->partOfName);
  350.         } while (0);
  351.     
  352.     UseResFile(currentResFile);
  353.  
  354.     return error;
  355. }
  356.  
  357. void DoSaving()
  358. {
  359.     short                kind;
  360.     Handle                item;
  361.     Rect                bounds;
  362.     Str255                topic;
  363.     OSErr                error;
  364.     StandardFileReply    reply;
  365.     short                currentResFile    = CurResFile();
  366.     SoundByteWindowPtr    window             = (SoundByteWindowPtr)FrontWindow();
  367.     Boolean             fileSaved        = (window->resRef != kNonExistentFileRef);
  368.     
  369.     if (fileSaved)
  370.         SaveToDisk(window, currentResFile);
  371.     else
  372.         {    
  373.         GetDItem((DialogPtr)window, iTopic, &kind, &item, &bounds);
  374.         GetIText(item, topic);
  375.  
  376.         StandardPutFile(kNullPString, topic, &reply);
  377.         
  378.         if (reply.sfGood)
  379.             {
  380.             do {
  381.                 if (reply.sfReplacing)
  382.                     {
  383.                     if (error = FSpDelete(&reply.sfFile))
  384.                         break;
  385.                     }
  386.                 FSpCreateResFile(&reply.sfFile, kSoundByteFileCreator, kSoundByteFileType, smSystemScript);
  387.                 if (error = ResError())
  388.                     break;
  389.                 window->resRef = FSpOpenResFile(&reply.sfFile, fsRdWrPerm);
  390.                 if (error = ResError())
  391.                     break;
  392.                 error = SaveToDisk(window, currentResFile);
  393.                 } while (0);
  394.     
  395.             AlertOSErr(error);
  396.             }
  397.         }
  398. }
  399.  
  400. void DoAppleMenu(short theItem)
  401. {
  402.     Str255    accName;
  403.     short    accNumber;
  404.     
  405.     switch (theItem) 
  406.         {
  407.         case iAbout:
  408.             DoAbout();
  409.             break;
  410.         default:
  411.             GetItem(GetMHandle(mApple), theItem, accName);
  412.             accNumber = OpenDeskAcc(accName);
  413.             break;
  414.         }
  415. }
  416.  
  417. void DoNewSoundByte()
  418. {
  419.     short                kind;
  420.     Handle                item;
  421.     Rect                bounds;
  422.     SoundByteWindowPtr    window;
  423.         
  424.     if (window = (SoundByteWindowPtr)NewPtrClear(sizeof(SoundByteWindow)))
  425.         {
  426.         GetNewDialog(rSoundByteDialog, (Ptr)window, kMoveToFront);
  427.         SetPort((WindowPtr)window);
  428.         GetDItem((DialogPtr)window, iAuthor, &kind, &item, &bounds);
  429.         SetDItem((DialogPtr)window, iAuthor, kind, (Handle)AuthorDrawProc, &bounds);
  430.         window->resRef = kNonExistentFileRef;
  431.         }
  432.     else
  433.         AlertOSErr(MemError());
  434. }
  435.  
  436. void DoClose()
  437. {
  438.     short                currentResFile    = CurResFile();
  439.     SoundByteWindowPtr    window             = (SoundByteWindowPtr)FrontWindow();
  440.     Boolean             fileSaved        = (window->resRef != kNonExistentFileRef);
  441.  
  442.     if (window->signature)
  443.         DisposHandle(window->signature);
  444.     if (window->sound)
  445.         DisposHandle(window->sound);
  446.     if (window->partOfName)
  447.         DisposHandle(window->partOfName);
  448.         
  449.     if (fileSaved)
  450.         {
  451.         CloseResFile(window->resRef);
  452.         UseResFile(currentResFile);
  453.         }
  454.     
  455.     CloseDialog((WindowPtr)window);
  456.     DisposPtr((Ptr)window);
  457. }
  458.  
  459. void DoOpen()
  460. {
  461.     OSErr                error;
  462.     short                kind;
  463.     Handle                item;
  464.     Rect                bounds;
  465.     StandardFileReply    reply;
  466.     SoundByteWindowPtr    window;
  467.     Handle                topicHandle     = nil;
  468.     short                currentResFile    = CurResFile();
  469.     SFTypeList            types            = { kSoundByteFileType };
  470.     
  471.     StandardGetFile(nil, 1, types, &reply);
  472.     
  473.     if (reply.sfGood)
  474.         {
  475.         DoNewSoundByte();
  476.         window = (SoundByteWindowPtr)FrontWindow();
  477.         
  478.         do {
  479.             if (window == nil)    // sanity check
  480.                 break;
  481.             window->resRef = FSpOpenResFile(&reply.sfFile, fsRdWrPerm);
  482.             if (error = ResError())
  483.                 break;
  484.             GetDItem((DialogPtr)window, iTopic, &kind, &item, &bounds);
  485.             UseResFile(window->resRef);
  486.             topicHandle = Get1Resource(kTopicResType, kTopicResID);
  487.             SetIText(item, (StringPtr)*topicHandle);
  488.             SelIText((DialogPtr)window, iTopic, 0, 254);
  489.             window->state = kUnkownState;
  490.             if (window->signature = Get1Resource(kSignatureResType, kSignatureResID))
  491.                 DetachResource(window->signature);
  492.             if (window->sound = Get1Resource(kSoundResType, kSoundResID))
  493.                 DetachResource(window->sound);
  494.             if (window->partOfName = Get1Resource(kNameResType, kNameResID))
  495.                 DetachResource(window->partOfName);
  496.             } while (0);
  497.         
  498.         UseResFile(currentResFile);
  499.         AlertOSErr(error);
  500.         }
  501. }
  502.  
  503. void DoFileMenu(short theItem)
  504. {
  505.     switch (theItem) 
  506.         {
  507.         case iNew:
  508.             DoNewSoundByte();
  509.             break;
  510.         case iOpen:
  511.             DoOpen();
  512.             break;
  513.         case iClose:
  514.             DoClose();
  515.             break;
  516.         case iSave:
  517.             DoSaving();
  518.             break;
  519.         case iQuit:
  520.             gEnvironment.running = false;
  521.             break;
  522.         }
  523. }
  524.  
  525. void DoEditMenu(short theItem)
  526. {
  527.     DialogPtr    dialog = FrontWindow();
  528.     
  529.     switch (theItem) 
  530.         {
  531.         case iCut:
  532.             ZeroScrap();
  533.             if (dialog) DlgCut(dialog);
  534.             break;
  535.         case iCopy:
  536.             ZeroScrap();
  537.             if (dialog) DlgCopy(dialog);
  538.             break;
  539.         case iPaste:
  540.             if (dialog) DlgPaste(dialog);
  541.             break;
  542.         case iSign:
  543.             DoSigning();
  544.             break;
  545.         case iVerify:
  546.             DoVerifying();
  547.             break;
  548.         }
  549. }
  550.  
  551. void DoRecording()
  552. {
  553.     OSErr                error;
  554.     Point                 loc        = {0, 0};
  555.     SoundByteWindowPtr    window     = (SoundByteWindowPtr)FrontWindow();
  556.     
  557.     LocalToGlobal(&loc);
  558.     loc.h += 75;
  559.     
  560.     if (window->sound)
  561.         DisposHandle(window->sound);
  562.  
  563.     if ((window->sound = GetTempHandle()) == nil)
  564.         error = MemError();
  565.     else
  566.         error = SndRecord(nil, loc, siGoodQuality, &window->sound);
  567.  
  568.     if (error == userCanceledErr && window->sound)
  569.         {
  570.         DisposHandle(window->sound);
  571.         window->sound = nil;
  572.         }
  573.     
  574.     if (window->state != kUnkownState)
  575.         {
  576.         window->state = kUnkownState;
  577.         DrawDialog((DialogPtr)window);
  578.         }
  579.     
  580.     AlertOSErr(error);
  581. }
  582.  
  583. void DoPlaying()
  584. {
  585.     OSErr                error;
  586.     SoundByteWindowPtr    window     = (SoundByteWindowPtr)FrontWindow();
  587.  
  588.     error = SndPlay(nil, window->sound, true);
  589.  
  590.     AlertOSErr(error);
  591. }
  592.  
  593. void DoSoundByteMenu(short theItem)
  594. {
  595.     switch (theItem) 
  596.         {
  597.         case iRecord:
  598.             DoRecording();
  599.             break;
  600.         case iPlay:
  601.             DoPlaying();
  602.             break;
  603.         }
  604. }
  605.  
  606. void DoMenuChoice(long menuChoice)
  607. {
  608.     short     theMenu;
  609.     short     theItem;
  610.         
  611.     if (menuChoice != 0) 
  612.         {
  613.         theMenu = hiword(menuChoice);
  614.         theItem = loword(menuChoice);
  615.         switch (theMenu) 
  616.             {
  617.             case mApple:
  618.                 DoAppleMenu(theItem);
  619.                 break;
  620.             case mFile:
  621.                 DoFileMenu(theItem);
  622.                 break;
  623.             case mEdit:
  624.                 DoEditMenu(theItem);
  625.                 break;
  626.             case mSoundByte:
  627.                 DoSoundByteMenu(theItem);
  628.                 break;
  629.             }
  630.         }
  631.  
  632.     HiliteMenu(0);
  633. }
  634.  
  635. void AdjustMenus()
  636. {    
  637.     MenuHandle            menu;
  638.     SoundByteWindowPtr    window = (SoundByteWindowPtr)FrontWindow();
  639.     
  640.     if (window)
  641.         {
  642.         menu = GetMHandle(mFile);
  643.         EnableItem(menu, iClose);
  644.         EnableItem(menu, iSave);
  645.         
  646.         menu = GetMHandle(mEdit);
  647.         EnableItem(menu, iCut);
  648.         EnableItem(menu, iCopy);
  649.         EnableItem(menu, iPaste);
  650.         EnableItem(menu, iSign);
  651.         window->signature ? EnableItem(menu, iVerify) : DisableItem(menu, iVerify);
  652.         
  653.         menu = GetMHandle(mSoundByte);
  654.         EnableItem(menu, iRecord);
  655.         window->sound ? EnableItem(menu, iPlay) : DisableItem(menu, iPlay);
  656.         }
  657.     else
  658.         {
  659.         menu = GetMHandle(mFile);
  660.         DisableItem(menu, iClose);
  661.         DisableItem(menu, iSave);
  662.         
  663.         menu = GetMHandle(mEdit);
  664.         DisableItem(menu, iCut);
  665.         DisableItem(menu, iCopy);
  666.         DisableItem(menu, iPaste);
  667.         DisableItem(menu, iSign);
  668.         DisableItem(menu, iVerify);
  669.  
  670.         menu = GetMHandle(mSoundByte);
  671.         DisableItem(menu, iRecord);
  672.         DisableItem(menu, iPlay);
  673.         }
  674.     
  675. }
  676.  
  677. void DoMouseDown(EventRecord *event)
  678. {
  679.     WindowPtr    whichWindow;
  680.     short        thePart;
  681.     long        menuChoice;
  682.             
  683.     thePart = FindWindow(event->where, &whichWindow);
  684.         
  685.     switch (thePart) 
  686.         {
  687.         case inMenuBar:
  688.             AdjustMenus();
  689.             menuChoice = MenuSelect(event->where);
  690.             DoMenuChoice(menuChoice);
  691.             break;
  692.         case inSysWindow:
  693.             SystemClick(event, whichWindow);
  694.             break;
  695.         case inDrag:
  696.             DragWindow(whichWindow, event->where, &qd.screenBits.bounds);
  697.             break;
  698.         case inGoAway:
  699.             if (TrackGoAway(whichWindow, event->where))
  700.                 DoClose();
  701.             break;
  702.         case inContent:
  703.             SelectWindow(whichWindow);
  704.             break;
  705.         case inDesk:
  706.             break;
  707.         }
  708. }
  709.  
  710. void DoKeyDown(EventRecord *event)
  711. {
  712.     char    charCode;
  713.     long    menuChoice;
  714.     
  715.     if (event->modifiers & cmdKey) 
  716.         {
  717.         charCode = event->message & charCodeMask;
  718.         if (charCode != 0)
  719.             {
  720.             AdjustMenus();
  721.             menuChoice = MenuKey(charCode);
  722.             DoMenuChoice(menuChoice);
  723.             }
  724.         }    
  725. }
  726.  
  727. void DoOSEvent(EventRecord    *event)
  728. {    
  729.     unsigned char    eventType;
  730.  
  731.     eventType = (unsigned char) (event->message >> 24) & 0x00ff;
  732.  
  733.     if (eventType == kSuspendResumeMessage)    
  734.         gEnvironment.inBackground = (event->message & kResumeMask) == 0;
  735. }
  736.  
  737. Boolean DoDialogEvent(EventRecord *event)
  738. {
  739.     short                item;
  740.     DialogPtr            dialog;
  741.     Boolean                handleEvent    = true;
  742.     SoundByteWindowPtr    window;
  743.  
  744.     if (DialogSelect(event, &dialog, &item))
  745.         {
  746.         if (!(event->what == keyDown && event->modifiers & cmdKey))
  747.             {
  748.             handleEvent = false;
  749.             window = (SoundByteWindowPtr)dialog;
  750.             if (window->state != kUnkownState)
  751.                 {
  752.                 window->state = kUnkownState;
  753.                 DrawDialog(dialog);
  754.                 }
  755.             }
  756.         }
  757.     
  758.     return handleEvent;
  759. }
  760.  
  761. void EventLoop()
  762. {
  763.     EventRecord    event;
  764.     Boolean        handleEvent;
  765.     
  766.     handleEvent = WaitNextEvent(everyEvent, &event, kMinSleep, kNilMouseRgn);
  767.  
  768.     if (IsDialogEvent(&event)) 
  769.         handleEvent = DoDialogEvent(&event);
  770.         
  771.     if (handleEvent) 
  772.         {
  773.         switch (event.what) 
  774.             {
  775.             case mouseDown:
  776.                 DoMouseDown(&event);
  777.                 break;
  778.             case app4Evt:
  779.                 DoOSEvent(&event);
  780.                 break;
  781.             case kHighLevelEvent:
  782.                 AEProcessAppleEvent(&event);
  783.                 break;
  784.             case autoKey:
  785.             case keyDown:
  786.                 DoKeyDown(&event);
  787.                 break;
  788.             case activateEvt:
  789.             case updateEvt:
  790.                 SetPort(FrontWindow());
  791.                 break;
  792.             }
  793.         }
  794. }
  795.  
  796. void main()
  797. {    
  798.     BasicInitializations();
  799.  
  800.     if (Prerequisites())
  801.         {
  802.         ApplicationStartup();    
  803.         while (gEnvironment.running) 
  804.             EventLoop();
  805.         }
  806.     else
  807.         DisplayUserAlert(kBadConfig, true, noErr);
  808. }
  809.  
  810.